Procedure VisualizarPedido(UnPedido:Pedido);
Begin
	Writeln ('Numero de Pedido: ', UnPedido.Numero);
	Writeln ('Fecha de Pedido: ',  UnPedido.Fecha);
	Writeln ('Electrodomestico: ', UnPedido.Electrodomestico);
End;

Procedure MensajeActualizacion(UnPedido:Pedido);
Begin
	ClrScr;
	Writeln ('------------------------------------------------');
	Writeln ('Se Reparo el pedido:');
	VisualizarPedido(UnPedido);    
	Writeln ('Toda la informacion fue actualizada');
	Writeln ('--Enter para continuar--');
	Readln;
	ClrScr;
End;

Function GenerarNumeroReparacion() : Word;
Var
	Archivo: FilePedidosReparados;
	UltimoPedido : PedidoReparado;

Begin
	OpenFilePedidosReparados(Archivo);

	If FileSize(Archivo) > 0 Then
	Begin

            	Seek(Archivo,FileSize(Archivo)-1);
            	Read(Archivo,UltimoPedido);
            	GenerarNumeroReparacion := UltimoPedido.Numero + 1;
	End
	Else
            	GenerarNumeroReparacion := 1;
            	{Primer registro}
   	 
	Close(Archivo);
End;

Function ObtenerPedidoAntiguo():Pedido;
Var
	PedidoArchivo : FilePedidos;
	UnPedido : Pedido;
Begin
	InicializarPedido(UnPedido);

	If (FileExists('Pedidos.dat')) Then
        Begin          
                OpenFilePedidos(PedidoArchivo);
	        Seek(PedidoArchivo,0);
	        {0 siempre que este ordenado y limpio}
	        Read(PedidoArchivo,UnPedido);    
                Close(PedidoArchivo);
        End;
	
        ObtenerPedidoAntiguo := UnPedido;
End;

Function BuscarRepuesto(RepuestoBuscado : Repuesto): Repuesto;   	 
Var
	Archivo : FileRepuestos;
	RepuestoTemporal : Repuesto;
	Minimo , Maximo , Medio : Integer;    
    
Begin
	OpenFileRepuestos(Archivo);
	Minimo  := 0;
	Maximo  := FileSize(Archivo);
	Medio   := 0;

	InicializarRepuesto(RepuestoTemporal);
	BuscarRepuesto := RepuestoTemporal;	 

	While ((RepuestoTemporal.Codigo <> RepuestoBuscado.Codigo) And (Minimo <= Maximo)) Do
	Begin            
            	Medio := (Minimo + Maximo) Div 2;   	 
            	Seek(Archivo,Medio);
            	Read(Archivo,RepuestoTemporal);
           	{Writeln('Codigo :',RepuestoTemporal.Codigo);}
            	 
            	If RepuestoBuscado.Codigo = RepuestoTemporal.Codigo Then
             	        BuscarRepuesto := RepuestoTemporal	 
            	Else If RepuestoBuscado.Codigo > RepuestoTemporal.Codigo Then
                	Minimo := Medio + 1
            	Else If RepuestoBuscado.Codigo < RepuestoTemporal.Codigo Then
                	Maximo := Medio - 1
            	Else
                Begin
                        {No encontro nada}
                        InicializarRepuesto(RepuestoTemporal);   
                        BuscarRepuesto := RepuestoTemporal;
                End;	 
        End;   	 
	Close(Archivo);
End;

Function BuscarPosicionRepuesto(RepuestoBuscado : Repuesto): Integer;   	 
Var
	Archivo : FileRepuestos;
	RepuestoTemporal : Repuesto;
	Minimo , Maximo , Medio : Integer;    
    
Begin
	OpenFileRepuestos(Archivo);
        {Busqueda Binaria}
	Minimo  := 0;
	Maximo  := FileSize(Archivo);
	Medio   := 0;

	BuscarPosicionRepuesto := -1;
    InicializarRepuesto(RepuestoTemporal);
	
    While ((RepuestoTemporal.Codigo <> RepuestoBuscado.Codigo) And (Minimo <= Maximo)) Do
	Begin
            Medio := (Minimo + Maximo) Div 2;   	 
            Seek(Archivo,Medio);
            Read(Archivo,RepuestoTemporal);
            	 
            If RepuestoBuscado.Codigo = RepuestoTemporal.Codigo Then
                    BuscarPosicionRepuesto := Medio    
            Else If RepuestoBuscado.Codigo > RepuestoTemporal.Codigo Then
                    Minimo := Medio +1
            Else If RepuestoBuscado.Codigo < RepuestoTemporal.Codigo Then
                    Maximo := Medio -1
            Else
                   {No encontro nada}
                    BuscarPosicionRepuesto := -1; 
	End;   	 
	Close(Archivo);
End;

Function CantidadUsada(Var RepuestoBuscado : Repuesto; UnPedidoCargado : PedidoReparado): Word;   	 
Var
	RepuestoTemporal : Repuesto;
	I , Maximo  : Integer;
	TotalUsado : Word;    
    
Begin
	TotalUsado := 0;
	Maximo := Length(UnPedidoCargado.RepuestosUtilizados);
	
	For I:= 1 To Maximo Do
	Begin
            	RepuestoTemporal := UnPedidoCargado.RepuestosUtilizados[I];    
           	 
            	If (RepuestoBuscado.Codigo = RepuestoTemporal.Codigo) Then   	 
                	TotalUsado := RepuestoTemporal.Cantidad + TotalUsado;
	End;

	CantidadUsada := TotalUsado;    
End;

Function ValidarRepuesto(Var UnRepuesto:Repuesto; NuevoPedidoReparado : PedidoReparado) : Boolean;
Var
	RepuestoEncontrado : Repuesto;
	RepuestosUsados : Word;
Begin
	InicializarRepuesto(RepuestoEncontrado);    
	RepuestoEncontrado := BuscarRepuesto(UnRepuesto);
	RepuestosUsados    := CantidadUsada(UnRepuesto,NuevoPedidoReparado);
    
	If (RepuestoEncontrado.Codigo = 0) Then
	Begin
            	Writeln('No Existen repuesto con ese codigo');
            	ValidarRepuesto := False;
	End
	Else If (RepuestoEncontrado.Cantidad < UnRepuesto.Cantidad) Then
	Begin
            	Writeln('No alcanza el stock para la reparacion');
            	ValidarRepuesto := False;
	End
	Else If ((RepuestosUsados <> 0) And ((RepuestoEncontrado.Cantidad - RepuestosUsados) < UnRepuesto.Cantidad)) Then
	Begin
            	Writeln('No alcanza el stock para la reparacion');
            	ValidarRepuesto := False;	 
	End  
	Else
           	ValidarRepuesto := True;

End;

Function BuscarRepuesto(Var RepuestosFaltantes:TP_RepuestosFaltantes; CodRepuesto: Word): TP_RepuestosFaltantes;
Const
	ERRORVACIO='Error en función "BuscarRepuesto": Lista vacia';
	ERRORNOENCONTRADO='No se ha encontrado el repuesto';
Var
	PAux : TP_RepuestosFaltantes;
Begin
        If (RepuestosFaltantes <> Nil) Then 
        Begin
        	PAux:= RepuestosFaltantes;
		While (PAux^.CodRepuesto = CodRepuesto) And (PAux=Nil) Do 
        	        PAux := PAux^.sgte;
		
	        If (PAux^.CodRepuesto = CodRepuesto) Then 
	                BuscarRepuesto:=PAux 
	        Else 
	                BuscarRepuesto:= RepuestosFaltantes;
	End 
	Else 
                Writeln(ERRORVACIO)
End;
		
Function ExisteRepuesto(Var RepuestosFaltantes:TP_RepuestosFaltantes; CodRepuesto: Word): boolean;
Var
	PAux : TP_RepuestosFaltantes;
Begin
	PAux:= RepuestosFaltantes;
	If (PAux <> Nil) Then
	Begin
	        While (PAux^.CodRepuesto <> CodRepuesto) Or (PAux <> Nil) Do 
	                PAux := PAux^.sgte;
			
                ExisteRepuesto:= (PAux^.CodRepuesto = CodRepuesto);
        End
        Else
                ExisteRepuesto := False; 
End;

Function ExistePedido(Var PedidosFaltantes:TP_PedidosFaltantes; NumPedido: Word): boolean;
Var
	PAux : TP_PedidosFaltantes;
Begin
	PAux:= PedidosFaltantes;
	While (PAux^.NumPedido <> NumPedido) Or (PAux <> Nil) Do 
	        PAux := PAux^.sgte;

	ExistePedido:=(PAux^.NumPedido = NumPedido)
End;
			
Procedure AgregarPedidoFaltante(Numero: word; Var VecRepuestos: TV_Repuestos; Var PedidosFaltantes: TP_PedidosFaltantes);
Var
        PAux: TP_PedidosFaltantes;	
Begin
	New(PAux);
	PAux^.NumPedido	     := Numero;
	PAux^.RtosFaltantes  := VecRepuestos;
	PAux^.sgte	     := PedidosFaltantes;
	PedidosFaltantes     := PAux;
End;

Procedure AgregarRepuestoFaltante(Var RepuestosFaltantes: TP_RepuestosFaltantes; Cod: Word; Var NuevoNodo: TP_RepuestosFaltantes);
Var
        PAux: TP_RepuestosFaltantes;
Begin        
	New(PAux);		
	PAux^.CodRepuesto       := Cod;
	PAux^.SubPedidos        := Nil;
	PAux^.sgte              := RepuestosFaltantes;	
	RepuestosFaltantes      := PAux;

	NuevoNodo               := PAux;	
End;
	
Procedure MeterSubPedidoRepuesto(Var SubPedidos:TP_PedidosFaltantes; Numero: word; Cant: Integer);
Var
	PAux: TP_PedidosFaltantes;
Begin
	New(PAux);

	PAux^.NumPedido         := Numero;
	PAux^.CantFaltante      := Cant;
	PAux^.sgte		:= SubPedidos;
	SubPedidos		:= PAux;
End;

Procedure CargaListaRepuestos (Var Pedido: PedidoReparado; Var VecRepuestos: TV_Repuestos; Var RepuestosFaltantes: TP_RepuestosFaltantes);
Var
	PAux:   TP_RepuestosFaltantes;
	PSAux:  TP_PedidosFaltantes;
	I:Byte;
	Codigo : Word;
Begin
	For I:= 1 To 10 Do 
	Begin
	        Codigo := VecRepuestos[I].CodRepuesto;
		If (Codigo <> 0) Then 
		Begin
                		        
			If (ExisteRepuesto(RepuestosFaltantes,Codigo)) Then 
               			PAux := BuscarRepuesto(RepuestosFaltantes, Codigo)
			Else 
			        AgregarRepuestoFaltante(RepuestosFaltantes, Codigo,PAux);
			
			MeterSubPedidoRepuesto(PAux^.SubPedidos, Pedido.Numero, Codigo);
			
			If Not(ExistePedido(PedidosFaltantes, Pedido.Numero)) Then 
	                        AgregarPedidoFaltante(Pedido.Numero, VecRepuestos, PedidosFaltantes);

		End;
        End;
End;

Procedure CargaListaPedidos (Var Pedido: PedidoReparado; Var  VecRepuestos: TV_Repuestos; Var PedidosFaltantes: TP_PedidosFaltantes);
Begin
	If Not(existePedido(PedidosFaltantes, Pedido.Numero)) Then 
	    AgregarPedidoFaltante(Pedido.Numero, VecRepuestos, PedidosFaltantes);
End;

Procedure DestruirSubPedidosRepuesto(Var SubPedidosRepuesto: TP_PedidosFaltantes);
Var
	PSAux : TP_PedidosFaltantes;
Begin
	PSAux := SubPedidosRepuesto;
	
	While (PSAux<>Nil) Do 
	Begin
		SubPedidosRepuesto := PSAux^.sgte;
		DISPOSE(PSAux);
		PSAux := SubPedidosRepuesto;
	End;
End;

Procedure InicializarVecFaltantes(Var VecRepuestosFaltantes: TV_Repuestos);
Var
        RepuestoVacio: TR_Repuestos;
        I : Integer;     
Begin
        RepuestoVacio.CantFaltante := 0;
        RepuestoVacio.CodRepuesto := 0;
        
        For I:=1 To 10 Do
               VecRepuestosFaltantes[I] := RepuestoVacio;
End;

Procedure CargaRespuestosNecesarios(Var NuevoPedidoReparado : PedidoReparado; Var PedidosFaltantes: TP_PedidosFaltantes; Var RepuestosFaltantes: TP_RepuestosFaltantes);
Var
   NuevoRepuesto,RepuestoEncontrado : Repuesto;
   ContadorPedido : Integer;
   Opcion : Char;
   VecRepuestosFaltantes: TV_Repuestos;

Begin
	ContadorPedido:= 1 ;
	Opcion := 'Y';
    
	InicializarRepuesto(NuevoRepuesto);
	InicializarRepuesto(RepuestoEncontrado);    
        InicializarVecFaltantes(VecRepuestosFaltantes);    
    
	While ((ContadorPedido <= 10) And (Opcion = 'Y')) Do
	Begin
            	Writeln('Repuesto : ',ContadorPedido,'/10');
            	Write('Ingrese Codigo de Respuesto:');        	
            	Readln(NuevoRepuesto.Codigo);

            	Write('Ingrese Cantidad: ');
            	Readln(NuevoRepuesto.Cantidad);
        	            		        
	        VecRepuestosFaltantes[ContadorPedido].CantFaltante := NuevoRepuesto.Cantidad;
	        VecRepuestosFaltantes[ContadorPedido].CodRepuesto  := NuevoRepuesto.Codigo;

            	If ValidarRepuesto(NuevoRepuesto,NuevoPedidoReparado) Then
            	Begin
                        NuevoPedidoReparado.RepuestosUtilizados[ContadorPedido] := NuevoRepuesto;
                        ContadorPedido := ContadorPedido + 1;
            	End
            	Else
            	Begin            	                	
                        CargaListaRepuestos(NuevoPedidoReparado, vecRepuestosFaltantes, RepuestosFaltantes);
                	{CargaListaPedidos(NuevoPedidoReparado, vecRepuestosFaltantes, PedidosFaltantes);}
		End;
            	If ContadorPedido < 10 Then
            	Begin
                	Writeln('Quiere Ingresar otro Respuesto? (Y/N)');
                	Readln (Opcion);
                	ClrScr;
            	End
 	End;
End;

Function NoEstaVacio(RepuestosArray :ArrayRepuestos) : Boolean;
Var
	I, Maximo,CantidadDeRepuestos: Integer;
	RepuestoCargado : Repuesto;
Begin

	Maximo := Length(RepuestosArray);
	CantidadDeRepuestos:= 0;

	For I:=1 To Maximo Do
	Begin
    	        RepuestoCargado := RepuestosArray[I];
    	        If (RepuestoCargado.Codigo <> 0) Then
            	        CantidadDeRepuestos := CantidadDeRepuestos +1;
	End;
	
	NoEstaVacio := (CantidadDeRepuestos > 0);
    
End;

Procedure ActualizarPedidosReparados(Var NuevoPedidoReparado : PedidoReparado);
Var
	Archivo : FilePedidosReparados;
    
Begin
        If  NoEstaVacio(NuevoPedidoReparado.RepuestosUtilizados) Then
	Begin    
            	OpenFilePedidosReparados(Archivo);
            	Seek(Archivo,FileSize(Archivo));
            	Write(Archivo,NuevoPedidoReparado);
            	Close(Archivo);
	End;       	 
            
End;

Procedure ActualizarFilePedidos(UltimoPedido : Pedido);
Var
	Archivo ,TMPFile  : FilePedidos;
	Maximo : Word;
	I : Integer;
	PedidoTemporal : Pedido;
Begin
	OpenFilePedidos(Archivo);
	OpenFilePedidosTemporal(TMPFile);
	
	{
	Teoricamente siempre seria el primero, 
	pero agrego la posibilidad de que no lo sea.
	}
	Maximo := FileSize(Archivo) - 1;
	For I:= 0 To Maximo Do
	Begin
                Seek(Archivo,I);
            	Read(Archivo,PedidoTemporal);
            	
            	If (PedidoTemporal.Numero <> UltimoPedido.Numero) Then   	 
                        Write(TMPFile,PedidoTemporal);

        End;
            
        Close(Archivo);
        Erase(Archivo);

        Close(TMPFile);
        Rename(TMPFile,'Pedidos.dat');
        {
	Si no quedaron pedidos pendientes de reparación, 
	Elimino el archivo. Más adelante valido que exista el archivo
	}
        If (I = 0) Then
                Erase(TMPFile);
End;

Procedure ActualizarCantidadesRepuestos(Var NuevoPedidoReparado: PedidoReparado);
Var
	NuevoRepuesto, RepuestoTemporal : Repuesto;
	Archivo : FileRepuestos;
	Maximo : Word;
	I,Posicion : Integer;
Begin
	Maximo := Length(NuevoPedidoReparado.RepuestosUtilizados);
	For I:=1 To Maximo Do
	Begin
            	NuevoRepuesto := NuevoPedidoReparado.RepuestosUtilizados[I];            	
            	If NuevoRepuesto.Codigo <> 0 Then
            	Begin   	
                  	Posicion := BuscarPosicionRepuesto(NuevoRepuesto);
                	If Posicion > -1 Then
                	Begin
     	                        OpenFileRepuestos(Archivo);
                            	Seek(Archivo,Posicion);
				{
				Cuando lee avanza 1 posición en el seek, 
				no se si es bueno o malo, 
				pero me costo mucho encontrarlo
				}                            	
				Read(Archivo,RepuestoTemporal);
               	                RepuestoTemporal.Cantidad := (RepuestoTemporal.Cantidad - NuevoRepuesto.Cantidad);
                            	Seek(Archivo,Posicion);                            	
				Write(Archivo,RepuestoTemporal);
                	        Close(Archivo);
                	End;
            	End;
	End;        
End;

Procedure RegistrarReparacion(Var PedidosFaltantes: TP_PedidosFaltantes; Var RepuestosFaltantes: TP_RepuestosFaltantes);
Var
	PedidoAntiguo : Pedido;
	NuevoPedidoReparado : PedidoReparado;
        Mensaje : String;
Begin
	        
        PedidoAntiguo := ObtenerPedidoAntiguo();
        
        If (PedidoAntiguo.Numero <> 0) Then
        Begin
	        InicializarReparados(NuevoPedidoReparado);
	        VisualizarPedido(PedidoAntiguo);
	        CargaRespuestosNecesarios(NuevoPedidoReparado, PedidosFaltantes, RepuestosFaltantes);

                If NoEstaVacio(NuevoPedidoReparado.RepuestosUtilizados) Then
                Begin
	                NuevoPedidoReparado.Numero := GenerarNumeroReparacion();
	                NuevoPedidoReparado.Fecha  := CalcularFechaHoy();
	                
                	ActualizarPedidosReparados(NuevoPedidoReparado);
                        ActualizarFilePedidos(PedidoAntiguo);
                        ActualizarCantidadesRepuestos(NuevoPedidoReparado);
            
	                MensajeActualizacion(PedidoAntiguo);
	        End
	        Else
	        Begin
                       Mensaje := 'No se cargaron repuestos. No se reparara el pedido'; 	       
	               MensajeDelSistema(Mensaje);
	        End
	End
	Else
	Begin
	        Mensaje := 'No hay pedidos pendientes de reparacion';
                MensajeDelSistema(Mensaje);
        End;

End;
